# -*- coding: UTF-8 -*-

import logging
import pytz
import requests
from datetime import datetime

from commons.cache.redis_utils import RedisCache

_logger = logging.getLogger(__name__)


def singleton(cls):
    instances = {}

    def get_instance(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]

    return get_instance


@singleton
class ApiHelper_iot(object):

    def __init__(self, host, base_url, appKey, appSecret):
        self.host = host
        self.base_url = base_url
        self.appKey = appKey
        self.appSecret = appSecret

    @property
    def token(self):
        token = RedisCache.get('iot_token')
        if not token:
            data = {'appKey': self.appKey, 'appSecret': self.appSecret}
            url = f'{self.host}{self.base_url}/auth/token'
            result = requests.post(url, json=data)
            token = self.check_result(result)['developerAuthToken']
            # 当前token只有当天有效,到了第二天0点会失效
            now = datetime.now(tz=pytz.timezone('Asia/Shanghai')).replace(microsecond=0).replace(tzinfo=None)
            expire_time = datetime(now.year, now.month, now.day, 23, 59, 59)
            total_seconds = int((expire_time - now).total_seconds())
            RedisCache.set('iot_token', token, total_seconds)
        return token

    def check_result(self, response):
        if response.status_code == 200:
            data = response.json()
            if data.get('code') == 200:
                return data.get('data', {})
            else:
                raise ValueError(f"API Error: {data.get('message')}")
        raise ValueError("API request failed with status: {}".format(response.status_code))

    def http_request(self, url, data):
        """
        带token的post请求
        """
        headers = {
            'Auth-Token': self.token
        }
        try:
            result = requests.post(url, json=data, headers=headers)
            return self.check_result(result)
        except requests.RequestException as e:
            _logger.error(f"Request failed: {e}")
            raise

    # 获取产品类型
    def get_product_type(self):
        """
        [{'b94aefa814d8d546': '照明'},{'b4aaeda15df6076e': '智能电表'}]
        对应数据字典里面的code和name
        """
        url = f'{self.host}{self.base_url}/product/type'
        result = self.http_request(url, {})
        return [{item['id']: item['name']} for item in result.get('list', [])]

    # 获取项目列表
    def get_project(self):
        url = f'{self.host}{self.base_url}/project/list'
        result = self.http_request(url, {"page": 1, "pageSize": 10})
        return result['list'][0].get('id', '') if result['list'] else ''

    def get_productList(self, projectId, productTypeId):
        """
        根据项目id以及产品类型获取产品信息
        """
        url = f'{self.host}{self.base_url}/project/productList'
        result = self.http_request(url, {"projectId": projectId, "productTypeId": productTypeId})
        return result.get('list', [])

    def get_productTSL(self, productId, productVersionId):
        """
        获取产品物模型
        """
        url = f'{self.host}{self.base_url}/product/productTSL'
        result = self.http_request(url, {"productId": productId, "productVersionId": productVersionId})
        return result

    def get_device(self, projectId, productId,page, pageSize):
        """
        获取设备列表
        """
        url = f'{self.host}{self.base_url}/device/list'
        headers = {
            'Auth-Token': self.token
        }
        result = requests.post(url, json={
            "projectId": projectId,
            "productId": productId,
            "page": page,
            "pageSize": pageSize
        }, headers=headers)

        total = result.json()['data']['total']
        items = result.json()['data']['list']
        return total, items


    def get_iot_device_configuration(self, project_id):
        """
        获取物联设备配置
        """
        device_configuration_list = []
        _field_map = {
            "productId": "productId",
            "name": "device_type",
            "model": "device_model",
            "supplierName": "manufacturer"
        }

        # 尝试一次性获取并处理productTypeIds，假设get_product_type()返回的是列表包含字典
        try:
            for product_info in self.get_product_type():
                productTypeId = next(iter(product_info))  # 直接获取字典的第一个key作为productTypeId
                product_type = product_info.get(productTypeId, '')  # 获取设备类型名称
                products = self.get_productList(project_id, productTypeId)

                if products:
                    product = products[0]  # 假设只关心第一个产品信息
                    # 使用字典推导式根据_field_map映射字段
                    config_item = {v: product.get(k, '') for k, v in _field_map.items()}
                    # 特殊处理productVersionIds，因为它需要从versionList中提取
                    config_item['productVersionIds'] = [
                        version.get('productVersionId', '') for version in product.get('versionList', [])
                    ]
                    config_item['is_sync'] = True
                    config_item['product_type'] = product_type
                    device_configuration_list.append(config_item)
        except Exception as e:
            raise ValueError(f"Failed to get device configuration: {e}")

        return device_configuration_list

    def get_iot_device_property(self, productId, productVersionId):

        """
        获取物联设备属性、属性字段、控制方法
        """

        _field_map = {
            "name": "name",
            "identifier": "identifying",
            "dataType": "fileType",
            "desc": "description"
        }
        property = {}
        property_field = []
        control_method = []
        productTSLs = self.get_productTSL(productId, productVersionId)
        if productTSLs['functionBlocks']:
            for functionBlock in productTSLs['functionBlocks']:
                if functionBlock['functionBlock']:
                    property['table_name'] = functionBlock['functionBlock']['name'] or ''
                    property['table_identifying'] = functionBlock['functionBlock']['identifier'] or ''
                    property['description'] = functionBlock['functionBlock']['desc'] or ''

                if functionBlock['properties']:
                    for prop in functionBlock['properties']:
                        property_field.append({v: prop.get(k, '') for k, v in _field_map.items()})

                if functionBlock['services']:
                    for service in functionBlock['services']:
                        control_method.append({
                            "name": service.get('name', ''),
                            "requestAddress": service.get('identifier', ''),
                            "description": service.get('desc', ''),
                            "requestParameters": service.get('inputData', [])
                        })
        return property, property_field, control_method


from system_config import SysCfg

HOST = SysCfg.C('iot.host', str, 'http://10.201.97.16:9003')
BASE_URL = SysCfg.C('iot.base_url', str, '/iotApiGw/1.0.0')
APP_KEY = SysCfg.C('iot.appKey', str, 'ce23ea2a67195c24')
APP_SECRET = SysCfg.C('iot.appSecret', str, 'b20d651ec16965ee')
A_iot = ApiHelper_iot(HOST, BASE_URL, APP_KEY, APP_SECRET)

if __name__ == '__main__':
    host = 'http://10.201.97.16:9003'
    base_url = '/iotApiGw/1.0.0'
    appKey = 'ce23ea2a67195c24'
    appSecret = 'b20d651ec16965ee'

    a = ApiHelper_iot(host, base_url, appKey, appSecret)
    project_id = a.get_project()

    result, total = a.get_device(project_id, 'a25ca6d02594cb64')
    print(result, total)

    # print(a.get_product_type())
    # productTypeIds = [list(d.keys())[0] for d in a.get_product_type()]
    # print(productTypeIds)

    # b = a.get_iot_device_configuration(project_id)
    #
    # for i in b:
    #     productId = i.get('productId', '')
    #     productVersionIds = i.get('productVersionIds', [])
    #     for productVersionId in productVersionIds:
    #         property, property_field, control_method = a.get_iot_device_property(productId, productVersionId)
    #         # print(productId,productVersionIds,property, property_field)
    #         print(property, property_field, control_method)

    # for productTypeId in productTypeIds:
    #     products = a.get_productList(project_id, productTypeId)
    #     if products:
    #         productId = products[0].get('productId', '')  # 产品ID
    #         name = products[0].get('name', '')  # 设备类型名称
    #         model = products[0].get('model', '')  # 产品型号
    #         supplierName = products[0].get('supplierName', '')  # 供应商名称
    #         versionList = products[0].get('versionList', [])
    #         productVersionIds = [item.get('productVersionId') for item in versionList]
    #
    #         print({
    #             'productId': productId,
    #             'name': name,
    #             'model': model,
    #             'supplierName': supplierName,
    #             'productVersionIds': productVersionIds
    #         })
